using UnityEngine;
using UnityEngine.Events;

[RequireComponent(typeof(RectTransform))]
public class UIBezierMover : MonoBehaviour
{
    [Header("曲线定义 (三点贝塞尔曲线)")]
    [Tooltip("曲线起点")]
    public RectTransform startPoint;
    [Tooltip("曲线控制点")]
    public RectTransform controlPoint;
    [Tooltip("曲线终点")]
    public RectTransform endPoint;

    [Header("移动设置")]
    [Tooltip("移动速度 (单位：曲线长度/秒)")]
    public float moveSpeed = 100f;
    [Tooltip("是否自动开始移动")]
    public bool autoStart = true;
    [Tooltip("是否循环移动")]
    public bool loop = false;
    [Tooltip("往返模式 (仅在循环开启时有效)")]
    public bool pingPong = false;
    [Tooltip("开始前延迟时间")]
    public float startDelay = 0f;

    [Header("事件")]
    [Tooltip("移动开始时触发")]
    public UnityEvent onMoveStart;
    [Tooltip("移动结束时触发")]
    public UnityEvent onMoveEnd;

    private RectTransform uiRect; // 要移动的UI元素
    private float t = 0f; // 曲线进度 (0~1)
    private float currentDelay = 0f; // 当前延迟计时
    private bool isMoving = false; // 是否正在移动
    private bool isReversing = false; // 是否在反向移动 (仅用于往返模式)
    private float curveLength = 0f; // 曲线总长度
    private const int lengthSampleCount = 100; // 计算曲线长度的采样点数

    private void Awake()
    {
        uiRect = GetComponent<RectTransform>();
        
        // 计算曲线总长度（预计算用于速度控制）
        CalculateCurveLength();
    }

    private void Start()
    {
        if (autoStart)
        {
            StartMovement();
        }
    }

    private void Update()
    {
        if (!isMoving)
        {
            // 处理开始延迟
            if (currentDelay < startDelay)
            {
                currentDelay += Time.deltaTime;
                if (currentDelay >= startDelay)
                {
                    isMoving = true;
                    onMoveStart?.Invoke();
                }
            }
            return;
        }

        // 计算当前帧应该移动的进度
        if (curveLength > 0)
        {
            float tStep = (moveSpeed * Time.deltaTime) / curveLength;
            
            // 根据方向更新进度
            if (isReversing)
            {
                t -= tStep;
                if (t <= 0f)
                {
                    t = 0f;
                    HandleMovementEnd();
                }
            }
            else
            {
                t += tStep;
                if (t >= 1f)
                {
                    t = 1f;
                    HandleMovementEnd();
                }
            }
        }

        // 更新UI位置
        UpdateUIPosition();
    }

    /// <summary>
    /// 计算二次贝塞尔曲线上的点
    /// </summary>
    /// <param name="t">进度 (0~1)</param>
    /// <returns>曲线上对应点的位置</returns>
    private Vector2 GetBezierPoint(float t)
    {
        if (startPoint == null || controlPoint == null || endPoint == null)
        {
            return uiRect.anchoredPosition;
        }

        t = Mathf.Clamp01(t);
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;

        // 二次贝塞尔曲线公式: B(t) = u²P0 + 2utP1 + t²P2
        return uu * startPoint.anchoredPosition + 
               2 * u * t * controlPoint.anchoredPosition + 
               tt * endPoint.anchoredPosition;
    }

    /// <summary>
    /// 更新UI元素的位置到曲线上对应进度的点
    /// </summary>
    private void UpdateUIPosition()
    {
        uiRect.anchoredPosition = GetBezierPoint(t);
    }

    /// <summary>
    /// 计算曲线总长度（通过采样估算）
    /// </summary>
    private void CalculateCurveLength()
    {
        curveLength = 0f;
        Vector2 prevPoint = GetBezierPoint(0f);
        
        for (int i = 1; i <= lengthSampleCount; i++)
        {
            float sampleT = (float)i / lengthSampleCount;
            Vector2 currentPoint = GetBezierPoint(sampleT);
            curveLength += Vector2.Distance(prevPoint, currentPoint);
            prevPoint = currentPoint;
        }
    }

    /// <summary>
    /// 处理移动结束逻辑
    /// </summary>
    private void HandleMovementEnd()
    {
        onMoveEnd?.Invoke();

        if (loop)
        {
            if (pingPong)
            {
                // 往返模式：切换方向
                isReversing = !isReversing;
            }
            else
            {
                // 循环模式：重置到起点
                t = 0f;
            }
        }
        else
        {
            // 非循环模式：停止移动
            isMoving = false;
        }
    }

    /// <summary>
    /// 开始移动
    /// </summary>
    public void StartMovement()
    {
        currentDelay = 0f;
        t = isReversing ? 1f : 0f;
        UpdateUIPosition();
        isMoving = false; // 会在延迟后自动开启
    }

    /// <summary>
    /// 停止移动
    /// </summary>
    public void StopMovement()
    {
        isMoving = false;
    }

    /// <summary>
    /// 重置移动（回到起点）
    /// </summary>
    public void ResetMovement()
    {
        t = 0f;
        isReversing = false;
        currentDelay = 0f;
        isMoving = false;
        UpdateUIPosition();
    }

    /// <summary>
    /// 立即跳转到曲线指定进度位置
    /// </summary>
    /// <param name="progress">进度 (0~1)</param>
    public void JumpToProgress(float progress)
    {
        t = Mathf.Clamp01(progress);
        UpdateUIPosition();
    }

    // 在编辑器中绘制曲线
    private void OnDrawGizmosSelected()
    {
        if (startPoint == null || controlPoint == null || endPoint == null)
            return;

        // 绘制控制点连线
        Gizmos.color = Color.gray;
        Gizmos.DrawLine(startPoint.position, controlPoint.position);
        Gizmos.DrawLine(controlPoint.position, endPoint.position);

        // 绘制贝塞尔曲线
        Gizmos.color = Color.green;
        Vector2 prevWorldPoint = startPoint.position;
        
        for (int i = 1; i <= 50; i++)
        {
            float t = (float)i / 50;
            Vector2 bezierPoint = GetBezierPoint(t);
            Vector2 currentWorldPoint = startPoint.parent.TransformPoint(bezierPoint); // 转换为世界坐标
            Gizmos.DrawLine(prevWorldPoint, currentWorldPoint);
            prevWorldPoint = currentWorldPoint;
        }

        // 标记三个关键点位
        Gizmos.color = Color.blue;
        Gizmos.DrawWireSphere(startPoint.position, 8f); // 起点（蓝色）
        
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(controlPoint.position, 6f); // 控制点（黄色）
        
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(endPoint.position, 8f); // 终点（红色）
    }
}